package cn.st4rlight.util.regexp;

import java.util.regex.Matcher;

import org.apache.commons.lang3.StringUtils;

import cn.st4rlight.util.value.NumberUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 敏感信息脱敏工具
 *
 * @author st4rlight <st4rlight@163.com>
 * Created on 2024-05-04
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SensitiveUtil {

    /**
     * 手机号脱敏
     * 133****3333
     */
    public static String maskMobilePhone(String mobilePhone) {
        return maskMidStr(mobilePhone, 3, 4);
    }

    /**
     * 身份证号脱敏
     * 511321************
     */
    public static String maskIdentityNo(String identityNo) {
        return maskMidStr(identityNo, 6, 0);
    }

    /**
     * 主体名称脱敏
     */
    public static String maskCorpName(String corpName) {
        corpName = StringUtils.trimToEmpty(corpName);
        int length = corpName.length();
        if (length <= 3) {
            return corpName;
        }
        return maskMidStr(corpName, length / 3, length / 3);
    }

    /**
     * 姓名脱敏，小于2个字直接返回，两个字保留首字，大于3个保留首尾
     * 啊：啊
     * 于敏：于*
     * 钱学森：钱*森
     * 爱新觉罗：爱**罗
     */
    public static String maskName(String name) {
        name = StringUtils.trimToEmpty(name);
        int length = name.length();
        if (length < 2) {
            return name;
        } else if (length == 2) {
            return name.charAt(0) + "*";
        } else {
            return name.charAt(0) + "*".repeat(length - 2) + name.charAt(length - 1);
        }
    }

    /**
     * 用户昵称脱敏
     * 头尾各保留三分之一长度
     */
    public static String maskUserName(String userName) {
        userName = StringUtils.trimToEmpty(userName);
        if (userName.length() <= 4) {
            return userName;
        }

        int  leftIndex = userName.length() / 3;
        int rightIndex = userName.length() * 2 / 3;
        String mask = "*".repeat(rightIndex - leftIndex + 1);
        return userName.substring(0, leftIndex) + mask + userName.substring(rightIndex + 1);
    }

    /**
     * 邮箱脱敏 @前字符保留尾一半，@后完全保留，奇数时优先保留
     * 示例： abc001@136.com     ***001@136.com
     * 示例： st4rlight@163.com  ****light@163.com
     */
    public static String maskEmail(String email) {
        if (StringUtils.isEmpty(email)) {
            return email;
        }

        // 没有@或者@在第一个字符上，直接返回
        int atIndex = email.indexOf('@');
        if (atIndex <= 0) {
            return email;
        }

        // @前部保留一半
        String prefix = email.substring(0, atIndex);
        int prefixHalfLength = prefix.length() / 2;

        StringBuilder builder = new StringBuilder();
        builder.append(StringUtils.repeat('*', prefixHalfLength));
        builder.append(prefix.substring(prefixHalfLength));
        // 保留@后面的部分
        builder.append(email.substring(atIndex));

        return builder.toString();
    }

    /**
     * 隐藏userId信息
     * 头尾各保留3位，中间替代为*号，长度不够则直接返回
     */
    public static String maskUserId(Long userId) {
        if (!NumberUtil.isPositive(userId)) {
            return "";
        }

        String userIdStr = String.valueOf(userId);
        if (userIdStr.length() <= 6) {
            return userIdStr;
        } else {
            String mask = "*".repeat(userIdStr.length() - 6);
            return userIdStr.substring(0, 3) + mask + userIdStr.substring(userIdStr.length() - 3);
        }
    }


    /**
     * 对字符串保留头尾，中间变为*号
     *
     * @param str 原始字符串
     * @param beginRetainLen 头部保留长度
     * @param endRetainLen 尾部保留长度
     * @return 修改后的字符串
     */
    private static String maskMidStr(String str, int beginRetainLen, int endRetainLen) {
        if (StringUtils.isEmpty(str) || beginRetainLen < 0 || endRetainLen < 0) {
            return str;
        }

        // 长度不够，直接返回
        if (beginRetainLen + endRetainLen >= str.length()) {
            return str;
        }

        // 头部保留
        StringBuilder builder = new StringBuilder(str.length() + 1);
        builder.append(str, 0, beginRetainLen);

        // 中间*号
        int maskLength = str.length() - beginRetainLen - endRetainLen;
        builder.append(StringUtils.repeat('*', maskLength));

        // 尾部保留
        builder.append(str.substring(str.length() - endRetainLen));

        return builder.toString();
    }

    /**
     * 地址脱敏
     */
    public static String maskAddress(String address) {
        if (StringUtils.isEmpty(address)) {
            return address;
        }
        Matcher match = RegExpUtil.getAddressMatcher(address);
        StringBuilder stringBuilder = new StringBuilder();
        boolean end = false;

        while (match.find()) {
            if (match.group("province") != null) {
                stringBuilder.append(match.group("province"));
            }
            if (match.group("city") != null) {
                stringBuilder.append(match.group("city"));
            }
            if (match.group("region") != null) {
                stringBuilder.append(match.group("region"));
                end = true;
            }

            if (end) {
                break;
            }
        }
        String tempResult = stringBuilder.toString();
        return tempResult + (new String(new char[address.length() - tempResult.length()]))
                .replace("\u0000", "*");
    }

    public static String maskBankCard(String bankCard) {
        if (StringUtils.isEmpty(bankCard)) {
            return bankCard;
        }
        return maskMidStr(bankCard, 4 , 4);
    }
}